package com.ruoyi.web.controller.kujiale;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.OperationLog;
import com.ruoyi.system.dto.design.OperationLogUpdateDTO;
import com.ruoyi.system.enums.BusinessTypeEnum;
import com.ruoyi.system.enums.OperateActionEnum;
import com.ruoyi.system.service.IOperationLogService;
import io.swagger.annotations.*;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * 操作日志相关控制器（含枚举字典查询接口，供前端获取操作动作列表）
 */
@RestController
@RequestMapping("/system/operationLog")
@Api(tags = "操作日志管理") // Swagger标签，归类接口
public class OperationLogController extends BaseController {


    @Autowired
    IOperationLogService operationLogService;

    /**
     * 接口功能：获取所有操作动作的编码与释义（前端下拉选择、字典渲染用）
     * 适用场景：日志筛选时的“操作动作”下拉框、操作记录表格的“动作类型”列显示
     */
    @GetMapping("/getOperateActionDict")
    @ApiOperation(value = "获取操作动作字典列表", notes = "返回所有操作动作的code（编码）和desc（中文释义），用于前端字典展示")
    public AjaxResult getOperateActionDict() {
        // 调用枚举的工具方法，获取封装后的VO列表
        List<OperateActionEnum.OperateActionVO> actionDictList = OperateActionEnum.getAllActionList();
        // 按统一响应格式返回（符合项目BaseController的AjaxResult规范）
        return AjaxResult.success("操作动作字典获取成功", actionDictList);
    }


    /**
     * 接口功能：按业务类型+业务ID查询操作日志
     * 适用场景：查询某业务的完整操作历史（如图纸ID=1001的所有操作日志）
     */
    @GetMapping("/listByBusiness")
    @ApiOperation(
            value = "按业务类型+业务ID查询日志",
            notes = "返回指定业务的所有操作历史，自动填充枚举中文标签（如业务类型“DESIGN”显示为“图纸设计”）"
    )
    public AjaxResult listByBusiness(
            @Parameter(
                    name = "businessType",
                    in = ParameterIn.QUERY,
                    required = true,
                    description = "业务类型（枚举code），可选值：DESIGN=图纸设计、ORDER=订单管理、USER=用户管理、CONFIG=系统配置",
                    schema = @Schema(allowableValues = {"DESIGN", "ORDER", "USER", "CONFIG"})
            )
            @RequestParam String businessType,

            @Parameter(
                    name = "businessId",
                    in = ParameterIn.QUERY,
                    required = true,
                    description = "业务关联ID（字符串形式，如图纸ID=1001则传“1001”，订单ID=2025则传“2025”）"
            )
            @RequestParam String businessId
    ) {
        try {
            // 1. 调用Service查询
            List<OperationLog> logs = operationLogService.getLogsByBusinessIdAndType(businessId, businessType);
            // 2. 返回统一响应格式
            return AjaxResult.success(
                    String.format("查询业务类型【%s】-业务ID【%s】的操作日志成功，共%d条",
                            BusinessTypeEnum.getByCode(businessType) != null ?
                                    BusinessTypeEnum.getByCode(businessType).getDesc() : businessType,
                            businessId,
                            logs.size()
                    ),
                    logs
            );
        } catch (IllegalArgumentException e) {
            // 参数错误（友好提示）
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            // 其他异常（隐藏细节，提示联系管理员）
            logger.error("查询操作日志失败：businessType={}, businessId={}", businessType, businessId, e);
            return AjaxResult.error("查询操作日志失败，请联系管理员");
        }
    }

    /**
     * 修改操作日志（仅允许修改备注、同步状态、操作来源等非核心字段）
     */
    @PutMapping("/update")
    @ApiOperation(
            value = "修改操作日志",
            notes = "仅允许修改备注、是否同步H5设计动态、操作来源字段，核心信息（如操作人、时间、业务类型）不可修改"
    )
    public AjaxResult update(
            @ApiParam(value = "日志修改参数（包含ID和要修改的字段）", required = true)
            @Valid @RequestBody OperationLogUpdateDTO updateDTO
    ) {
        try {
            return operationLogService.updateOperationLog(updateDTO);
        } catch (ServiceException e) {
            // 捕获业务异常（如权限不足、参数错误）
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            // 捕获系统异常（记录日志，隐藏细节）
            logger.error("修改操作日志失败：{}", updateDTO, e);
            return AjaxResult.error("修改日志失败，请联系管理员");
        }
    }


    @PostMapping("/save")
    @ApiOperation(
            value = "新增操作日志",
            notes = "1. 功能：记录系统操作行为，支持业务状态变更、文件操作、数据增删改等场景；\n" +
                    "2. 必选字段：operateUserId（操作人ID）、businessType（业务类型）、businessId（业务ID）、operateAction（操作动作）、operateSource（操作来源）；\n" +
                    "3. 可选字段：beforeStatus/afterStatus（仅状态变更场景必填）、remark（操作备注）、isSyncH5Design（默认0=不同步）；\n" +
                    "4. 特殊说明：operateTime若不传，系统自动填充当前时间；operateUserName建议从登录用户信息中获取，无需前端传递。"
    )
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "operationLog",
                    value = "操作日志实体（包含操作人、业务信息、操作动作等核心字段）",
                    required = true,
                    dataType = "OperationLog",
                    paramType = "body"
            )
    })
    public AjaxResult saveLog(
            @Valid @RequestBody OperationLog operationLog
    ) {
        try {
            boolean b = operationLogService.saveOperationLog(operationLog);
            return b ? AjaxResult.success() : AjaxResult.error();
        } catch (ServiceException e) {
            // 捕获业务异常（如权限不足、参数错误）
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            // 捕获系统异常（记录日志，隐藏细节）
            logger.error("保存操作日志失败：{}", operationLog, e);
            return AjaxResult.error("保存操作日志失败，请联系管理员");
        }
    }
}
